package com.tanhua.es.service;

import com.tanhua.es.pojo.UserLocationES;
import org.apache.lucene.queryparser.xml.builders.BooleanQueryBuilder;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.stereotype.Service;

import java.util.HashMap;

@Service
public class UserLocationService {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    public boolean updateUserLocation(Long userId, Double longitude, Double latitude, String address) {

        try {
            //判断索引库是否存在,如果不存在需要创建
            if (!this.elasticsearchTemplate.indexExists(UserLocationES.class)) {
                //创建索引
                this.elasticsearchTemplate.createIndex(UserLocationES.class);
            }
            //判断类型是否存在,如果不存在需要创建
            if (!this.elasticsearchTemplate.typeExists("tanhua", "user_location")) {
                //创建类型
                this.elasticsearchTemplate.putMapping(UserLocationES.class);
            }
            //判断用户的位置数据是否存在,如果存在则更新,不存在则插入
            GetQuery getQuery = new GetQuery();
            getQuery.setId(userId.toString());

            UserLocationES ul = this.elasticsearchTemplate.queryForObject(getQuery, UserLocationES.class);
            if (null == ul) {//插入
                UserLocationES userLocationES = new UserLocationES();
                userLocationES.setCreated(System.currentTimeMillis());
                userLocationES.setUpdated(userLocationES.getCreated());
                userLocationES.setLastUpdated(userLocationES.getCreated());
                userLocationES.setAddress(address);
                userLocationES.setUserId(userId);
                userLocationES.setLocation(new GeoPoint(latitude, longitude));
                //保存数据至es
                IndexQuery indexQuery = new IndexQueryBuilder().withObject(userLocationES).build();
                this.elasticsearchTemplate.index(indexQuery);
            } else {//更新

                HashMap<String, Object> map = new HashMap<>();
                map.put("lastUpdated", ul.getUpdated());
                map.put("updated", System.currentTimeMillis());
                map.put("address", address);
                map.put("location", new GeoPoint(latitude, longitude));

                UpdateRequest updateRequest = new UpdateRequest().doc(map);

                UpdateQuery updateQuery = new UpdateQueryBuilder().withId(userId.toString())
                        .withClass(UserLocationES.class)
                        .withUpdateRequest(updateRequest).build();
                this.elasticsearchTemplate.update(updateQuery);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public UserLocationES queryUserLocationByUserId(Long userId) {

        GetQuery getQuery = new GetQuery();
        getQuery.setId(userId.toString());
        return this.elasticsearchTemplate.queryForObject(getQuery, UserLocationES.class);
    }

    public Page<UserLocationES> queryUserFromLocation(Double longitude, Double latitude, Double distance, Integer page, Integer pageSize) {

        String fieldName = "location";

        //NativeSearchQuery实现了SearchQuery接口
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

        //设置分页
        PageRequest pageRequest = PageRequest.of(page - 1, pageSize);
        nativeSearchQueryBuilder.withPageable(pageRequest);

        //定义bool查询
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        //geo查询范围:指定圆心&半径
        GeoDistanceQueryBuilder geoDistanceQueryBuilder = new GeoDistanceQueryBuilder(fieldName);
        geoDistanceQueryBuilder.point(latitude, longitude);//圆心
        geoDistanceQueryBuilder.distance(distance / 1000, DistanceUnit.KILOMETERS);//半径

        boolQueryBuilder.must(geoDistanceQueryBuilder);//bool查询必须要满足geo的范围条件
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);

        //按照距离升序
        GeoDistanceSortBuilder geoDistanceSortBuilder = new GeoDistanceSortBuilder(fieldName, latitude, longitude);
        geoDistanceSortBuilder.unit(DistanceUnit.KILOMETERS);//单位
        geoDistanceSortBuilder.order(SortOrder.ASC);
        nativeSearchQueryBuilder.withSort(geoDistanceSortBuilder);

        return this.elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), UserLocationES.class);

    }
}
